import redis
import json
import threading
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)


class RedisMessageSystem:
    def __init__(self, host="localhost", port=6379):
        self.redis_pub = redis.Redis(host=host, port=port, decode_responses=True)
        self.redis_sub = self.redis_pub.pubsub()
        self.running = False

    def publish(self, channel, route_index, ce, dest_ip):
        """发布消息到指定频道"""
        message = json.dumps({"route_index": route_index, "ce": ce, "dest_ip": dest_ip})
        try:
            self.redis_pub.publish(channel, message)
            logging.info(
                f"消息已发布到 {channel}: route_index={route_index}, ce={ce}, dest_ip={dest_ip}"
            )
            return True
        except redis.RedisError as e:
            logging.error(f"发布失败: {e}")
            return False

    def subscribe(self, channel, callback):
        """订阅指定频道的消息"""
        try:
            self.redis_sub.subscribe(**{channel: callback})
            self.running = True
            logging.info(f"开始订阅频道: {channel}")

            # 启动监听线程
            self.listener = threading.Thread(target=self._listen)
            self.listener.daemon = True
            self.listener.start()
            return True
        except redis.RedisError as e:
            logging.error(f"订阅失败: {e}")
            return False

    def _listen(self):
        """内部方法：监听消息"""
        while self.running:
            try:
                message = self.redis_sub.get_message(
                    ignore_subscribe_messages=True, timeout=1.0
                )
                if message:
                    # 回调函数已在消息到达时处理
                    pass
            except redis.RedisError as e:
                logging.error(f"监听错误: {e}")
            except Exception as e:
                logging.error(f"系统错误: {e}")

    def unsubscribe(self, channel):
        """取消订阅"""
        try:
            self.redis_sub.unsubscribe(channel)
            self.running = False
            if self.listener.is_alive():
                self.listener.join(timeout=1.0)
            logging.info(f"已取消订阅: {channel}")
        except redis.RedisError as e:
            logging.error(f"取消订阅失败: {e}")


def message_handler(message):
    """自定义消息处理函数"""
    try:
        data = json.loads(message["data"])
        print(
            f"收到消息 [来自 {message['channel']}]: "
            f"route_index={data['route_index']}, "
            f"ce={data['ce']}, "
            f"dest_ip={data['dest_ip']}"
        )
    except (json.JSONDecodeError, KeyError) as e:
        logging.error(f"消息解析失败: {e}")
